/*
 * Copyright (c) 2009, Luke Emrose
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.  Neither the name of Luke Emrose Sole Trader nor the
 * names of its contributors may be used to endorse or promote
 * products derived from this software without specific prior written
 * permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 #ifndef __VORONOI_NOISE_H__
#define __VORONOI_NOISE_H__

#include "noisesGlobals.hpp"

// include for the sqrt function
#include <cmath>

// include for the RxCellNoise function
#include <rx.h>

/**
 * @brief
 * voronoi cell noise ( a.k.a. Worley noise ) -- 3-D, 1-feature version
 */
template < typename T >
inline static T voronoiNoise_f1_3d( T x, T y, T z, T jitter )
{
	T f1 = 1000;
	T pos1[ 3 ];

	T thiscell[ 3 ];
	thiscell[ 0 ] = floor( x ) + ( T ) 0.5;
	thiscell[ 1 ] = floor( y ) + ( T ) 0.5;
	thiscell[ 2 ] = floor( z ) + ( T ) 0.5;

	for( int i = -1;  i <= 1;  ++i )
	{
		for( int j = -1;  j <= 1;  ++j )
		{
			for( int k = -1;  k <= 1;  ++k )
			{
				T testcell[ 3 ];
				testcell[ 0 ] = thiscell[ 0 ] + i;
				testcell[ 1 ] = thiscell[ 1 ] + j;
				testcell[ 2 ] = thiscell[ 2 ] + k;

				T cellnoise[ 3 ];
				RtInt success = RxCellNoise( 3, testcell, 3, cellnoise );

				T pos[ 3 ];
				pos[ 0 ] = testcell[ 0 ] + jitter * ( cellnoise[ 0 ] - ( T ) 0.5 );
				pos[ 1 ] = testcell[ 1 ] + jitter * ( cellnoise[ 1 ] - ( T ) 0.5 );
				pos[ 2 ] = testcell[ 2 ] + jitter * ( cellnoise[ 2 ] - ( T ) 0.5 );

				T offset[ 3 ];
				offset[ 0 ] = pos[ 0 ] - x;
				offset[ 1 ] = pos[ 1 ] - y;
				offset[ 2 ] = pos[ 2 ] - z;

				T dist = ( offset[ 0 ] * offset[ 0 ] ) + ( offset[ 1 ] * offset[ 1 ] ) + ( offset[ 2 ] * offset[ 2 ] ); /* actually dist^2 */
				if( dist < f1 )
				{
					f1 = dist;
					pos1[ 0 ] = pos[ 0 ];
					pos1[ 1 ] = pos[ 1 ];
					pos1[ 2 ] = pos[ 2 ];
				}
			}
		}
	}

	// distance return arg
	f1 = sqrt( f1 );

	// point return arg
	//*retArg = f1;
	//( *retArg )[ 0 ] = pos1[ 0 ];
	//( *retArg )[ 1 ] = pos1[ 1 ];
	//( *retArg )[ 2 ] = pos1[ 2 ];

	return f1;
}

#endif